import glm
import numpy as np

class Camera:
    def __init__(self, position=glm.vec3(0.0, 0.0, 0.0), up=glm.vec3(0.0, 1.0, 0.0), yaw=-90.0, pitch=0.0,
                 front=glm.vec3(0.0, 0.0, -1.0), zoom=45.0):
        self.position = position
        self.world_up = up
        self.yaw = yaw
        self.pitch = pitch
        self.front = front
        self.zoom = zoom
        self.updateCameraVectors()

    def GetViewMatrix(self):
        return glm.lookAt(self.position, self.position + self.front, self.up)

    def updateCameraVectors(self):
        front_x = np.cos(glm.radians(self.yaw) * np.cos(glm.radians(self.pitch)))
        front_y = np.sin(glm.radians(self.pitch))
        front_z = np.sin(glm.radians(self.yaw) * np.cos(glm.radians(self.pitch)))
        self.front = glm.normalize(glm.vec3(front_x, front_y, front_z))

        self.right = glm.normalize(glm.cross(self.front, self.world_up))
        self.up = glm.normalize(glm.cross(self.right, self.front))
    
    def ProcessKeyboard(self, direction, velocity):
        velocity = 2.5 * velocity
        if direction == "FORWARD":
            self.position += self.front * velocity
        elif direction == "BACKWARD":
            self.position -= self.front * velocity
        elif direction == "LEFT":
            self.position -= self.right * velocity
        elif direction == "RIGHT":
            self.position += self.right * velocity
        elif direction == "UP":
            self.position += self.up * velocity
        elif direction == "DOWN":
            self.position -= self.up * velocity
        elif direction == "ROTATE_Positive":
            self.yaw += velocity * 30
        elif direction == "ROTATE_Negative":
            self.yaw -= velocity * 30
    
    def ProcessMouseMovement(self, xoffset, yoffset, constrainPitch=True):
        xoffset *= 0.1
        yoffset *= 0.1
        
        self.yaw += xoffset
        self.pitch += yoffset
        if constrainPitch:
            if self.pitch > 89.0:
                self.pitch = 89.0
            if self.pitch < -89.0:
                self.pitch = -89.0
        
        self.updateCameraVectors()

    def ProcessMouseScroll(self, yoffset):
        self.zoom -= (2 * yoffset)
        if self.zoom < 1.0:
            self.zoom = 1.0
        elif self.zoom > 90.0:
            self.zoom = 90.0